#include "httpserver.h"
#include "hook.h"
#include "logger.h"

#define SERVER_CERT_FILE "./cert.pem"
#define SERVER_PRIVATE_KEY_FILE "./key.pem"

using namespace httplib;

int *g_write_fd = NULL;
int *g_read_fd = NULL;

// std::vector<nmsp::Cont *> g_contp;
// nmsp::Cont *g_contp_arr[10] = {nullptr};


std::vector<nmsp::Cont *> g_contp;

namespace nmsp
{
    std::string dump_headers(const Headers &headers)
    {
        std::string s;
        char buf[BUFSIZ];

        for (auto it = headers.begin(); it != headers.end(); ++it)
        {
            const auto &x = *it;
            snprintf(buf, sizeof(buf), "%s: %s\n", x.first.c_str(), x.second.c_str());
            s += buf;
        }

        return s;
    }

    std::string log(const Request &req, const Response &res)
    {
        std::string s;
        char buf[BUFSIZ];

        s += "================================\n";

        snprintf(buf, sizeof(buf), "%s %s %s", req.method.c_str(),
                 req.version.c_str(), req.path.c_str());
        s += buf;

        std::string query;
        for (auto it = req.params.begin(); it != req.params.end(); ++it)
        {
            const auto &x = *it;
            snprintf(buf, sizeof(buf), "%c%s=%s",
                     (it == req.params.begin()) ? '?' : '&', x.first.c_str(),
                     x.second.c_str());
            query += buf;
        }
        snprintf(buf, sizeof(buf), "%s\n", query.c_str());
        s += buf;

        s += dump_headers(req.headers);

        s += "--------------------------------\n";

        snprintf(buf, sizeof(buf), "%d %s\n", res.status, res.version.c_str());
        s += buf;
        s += dump_headers(res.headers);
        s += "\n";

        if (!res.body.empty())
        {
            s += res.body;
        }

        s += "\n";

        return s;
    }

    //------------------------ Httpserver ----------------------------

    int Httpserver::Register()
    {
        if (!m_serv.is_valid())
        {
            printf("server has an error...\n");
            return -1;
        }

        m_serv.Get("/", [=](const Request & /*req*/, Response &res)
                   { res.set_redirect("/hi"); });

        m_serv.Get("/hi", [](const Request & /*req*/, Response &res)
                   { res.set_content("Hello World!\n", "text/plain"); });

        m_serv.Get("/slow", [](const Request & /*req*/, Response &res)
                   {
    std::this_thread::sleep_for(std::chrono::seconds(2));
    res.set_content("Slow...\n", "text/plain"); });

        m_serv.Get("/dump", [](const Request &req, Response &res)
                   { res.set_content(dump_headers(req.headers), "text/plain"); });

        m_serv.Get("/stop",
                   [&](const Request & /*req*/, Response & /*res*/)
                   { m_serv.stop(); });

        //...
        m_serv.Post("/post_json", [](const Request &req, Response &res)
                    {
                          res.set_content(req.body + '\n', "application/json");
                          // printf("body = %d\n", req.body.c_str());
                          // curl -X POST http://127.0.0.1:8080/post_json -H 'content-type:application/json' -d "{\"user\":\"root\", \"password\":\"admin\"}"
                          //
                          // m_serv 将请求转发给 client, 然后 client 去请求 POST 请求 activemq, 上传数据,
                          // 这里进程间通信使用管道, httpserver 是 子进程, client 是父进程,
                          //
                          // int result = write(*g_write_fd, req.body.c_str(), req.body.length()); });
                          write(*g_write_fd, req.body.c_str(), req.body.length()); });

        //...
        // curl -X POST http://192.168.100.81:8080/ys_provider/providerController/sendQueue.do  -H 'content-type:application/json' -d "{\"user\":\"root\", \"password\":\"admin\"}"
        // curl -X POST http://192.168.110.3:8088/providerController/sendQueue.do  -H 'content-type:application/json' -d "{\"user\":\"root\", \"password\":\"admin\"}"
        //...

        m_serv.set_error_handler([](const Request & /*req*/, Response &res)
                                 {
                        const char *fmt = "<p>Error Status: <span style='color:red;'>%d</span></p>";
                        char buf[BUFSIZ];
                        snprintf(buf, sizeof(buf), fmt, res.status);
                        res.set_content(buf, "text/html"); });

        m_serv.set_logger([](const Request &req, const Response &res)
                          { 
                            printf("%s", log(req, res).c_str()); 
                            MYLOG("%s", log(req, res).c_str()); });

        
        if (g_contp.empty())
        {
            MYLOG("g_contp is empty, not other register ...");
        }
        else
        {
            for (Cont *&contp : g_contp)
            {
                contp->SetServer(&m_serv);
                MYLOG("start route %s", contp->GetPattern().c_str());
                m_serv.Get(contp->GetPattern().c_str(), std::bind(&Cont::RegisterGet, contp, std::placeholders::_1, std::placeholders::_2));
            }
        }
        
        /***
        // nmsp::Cont *zero_contp_arr[10] = {nullptr};
        // if (0 == ::memcmp(zero_contp_arr, g_contp_arr, 10 * sizeof(nmsp::Cont *)))
        // {
        //     MYLOG("g_contp is empty, not other register ...");
        // }
        // else
        // {
        //     nmsp::Cont *tmp = nullptr;
        //     int idx = 0;
        //     do
        //     {
        //         tmp = g_contp_arr[idx];
        //         idx += 1;
        //         if (nullptr != tmp)
        //         {
        //             tmp->SetServer(&m_serv);
        //             MYLOG("start route %s", tmp->GetPattern().c_str());
        //             m_serv.Get(tmp->GetPattern().c_str(), std::bind(&Cont::RegisterGet, tmp, std::placeholders::_1, std::placeholders::_2));
        //         }
        //     } while (tmp != nullptr && idx < sizeof(g_contp_arr));
        // }
        ***/

        return 0;
    }
}
